using System;
using System.Linq;
using System.Collections.Generic;
using AppContext = T.ServiceComponent.Session.Service.AppContext;
using T.FAS.Runtime.DataAccess.SQLDom;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using T.FAS.Runtime.DataAccess.Common;

namespace T.FAS.Runtime.DataAccess.Engine
{
    /// <summary>
    /// InternationalTools
    /// </summary>
    public class InternationalTools
    {
        private const string internationalSessionKey = "t_locale";
        /// <summary>
        /// i18N特殊占位符，出现在CNO.Element.ID中标识这个Element元素为动态i18N类型
        /// </summary>
        private const string i18NSpecialChars = "_$i18N_";
        private static readonly object s_lockObj = new object();
        private static Dictionary<string, string> s_languageMapping;
        private static readonly IDACLogService s_localLogService = DACLogFactory.GetDACLogService();

        /// <summary>
        /// 是否将连字符转换为下划线
        /// </summary>
        public static bool IsConvertHyphenToUnderline = true;

        /// <summary>
        /// 获取数据多语言映射关系，例如{"Lang1", "zh-CN" }, {"Lang2", "en-US" }
        /// </summary>
        private static Dictionary<string, string> LanguageMapping
        {
            get
            {
                if (s_languageMapping == null)
                {
                    lock (s_lockObj)
                    {
                        if (s_languageMapping == null)
                        {
                            s_languageMapping = GetI18NDataMapping();
                        }
                    }
                }
                return s_languageMapping;
            }
        }

        /// <summary>
        /// 获取数据多语言映射关系，例如{"lang1", "zh-CN" }, {"lang2", "en-US" }
        /// </summary>
        /// <param name="mode"></param>
        /// <param name="specifiedLanguages"></param>
        /// <returns></returns>
        public static Dictionary<string, string> GetLanguageMapping(InternationalMode mode = InternationalMode.All, List<string> specifiedLanguages = null)
        {
            Dictionary<string, string> dict = new Dictionary<string, string>();
            try
            {
                if (mode == InternationalMode.All)
                    return LanguageMapping;
                else if (mode == InternationalMode.CurrentUser)
                {
                    string curLocale = "zh-CN";
                    try
                    {
                        //curLocale = AppContext.Current.Session[internationalSessionKey]?.ToString();
                        if (AppContext.Current.Language != null)
                        {
                            curLocale = AppContext.Current.Language.ID;
                        }
                        else
                        {
                            curLocale = AppContext.Current.Session[internationalSessionKey]?.ToString();
                        }
                        if (string.IsNullOrEmpty(curLocale))
                        {
                            //curLocale = "en-US";
                        }
                    }
                    catch
                    {
                    }
                    foreach (var pair in LanguageMapping)
                    {
                        if (pair.Value == curLocale)
                        {
                            dict[pair.Key] = pair.Value;
                        }
                    }
                }
                else
                {
                    if (specifiedLanguages != null)
                    {
                        foreach (var lang in specifiedLanguages)
                        {
                            foreach (var pair in LanguageMapping)
                            {
                                if (pair.Value == lang)
                                {
                                    dict[pair.Key] = pair.Value;
                                }
                            }
                        }
                    }
                }
                return dict;
            }
            catch (Exception ex)
            {
                s_localLogService.WriteError(ex, $"获取多语言字段映射失败");
                return dict;
            }
        }

        /// <summary>
        /// 获取国际化列的对应语言辅助列列名，用于TRecord中的多语言字段 例如 Name_en_US
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="i18NCode"></param>
        /// <returns></returns>
        public static string GetLogicFieldName(string columnName, string i18NCode)
        {
            if (IsConvertHyphenToUnderline)
                i18NCode = i18NCode.Replace('-', '_');
            return $"{columnName}_{i18NCode}";
        }

        /// <summary>
        /// 获取国际化列的对应语言辅助列列名后缀，用于从ChangeSetItem中反向提取字段
        /// </summary>
        /// <param name="i18NCode"></param>
        /// <returns></returns>
        public static string GetLogicFieldNameSuffix(string i18NCode)
        {
            if (IsConvertHyphenToUnderline)
                i18NCode = i18NCode.Replace('-', '_');
            return $"_{i18NCode}";
        }

        /// <summary>
        /// 获取国际化列的对应语言辅助列物理存储列名 例如 Name_lang1
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="i18NCode"></param>
        /// <param name="mapping"></param>
        /// <returns></returns>
        public static string GetRealFieldName(DataObject dataObject, string columnName, string i18NCode, Dictionary<string, string> mapping)
        {
            if (mapping.Values.Contains(i18NCode))
            {
                var langKey = mapping.FirstOrDefault(map => map.Value == i18NCode).Key;
                return DataColumn.GetInternationalColumnName(dataObject, columnName, langKey);
            }
            return null;
        }

        /// <summary>
        /// 获取国际化列的对应语言辅助列物理存储列名 例如 Name_lang1
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="langKey"></param>
        /// <returns></returns>
        public static string GetRealFieldName(DataObject dataObject, string columnName, string langKey)
        {
            return DataColumn.GetInternationalColumnName(dataObject, columnName, langKey);
        }

        /// <summary>
        /// 获取国际化列的元素对应的DataItem id 例如 xxxxx_$i18n_lang1
        /// </summary>
        /// <param name="dataObject"></param>
        /// <param name="ele"></param>
        /// <param name="langKey"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static string GetDataItemElementIDKey(DataObject dataObject, CompositeNodeObjectElement ele, string langKey)
        {
            var realFieldName = DataColumn.GetInternationalColumnName(dataObject, ele.DataColumn.ColumnName, langKey);
            if (string.IsNullOrEmpty(realFieldName))
                throw new Exception(string.Format(CommonStringClassEngine.InternationalTools_GetDataItemElementIDKey,ele.CompositeDataObjectID,ele.Alias,langKey));
            return $"{ele.ID}{i18NSpecialChars}{realFieldName}";
        }

        /// <summary>
        /// 获取国际化列的对应语言辅助列物理存储列名 例如 Name_lang1
        /// </summary>
        /// <param name="dataItemKey"></param>
        /// <param name="realFieldName"></param>
        /// <param name="elementid"></param>
        /// <returns></returns>
        public static bool IsI18NDataItemElementIDKey(string dataItemKey, out string realFieldName, out string elementid)
        {
            elementid = dataItemKey;
            realFieldName = null;
            int ind = dataItemKey.IndexOf(i18NSpecialChars);
            if (ind > 0)
            {
                realFieldName = dataItemKey.Substring(ind + 7);
                elementid = dataItemKey.Substring(0, ind);
                return true;
            }
            return false;
        }

        private static Dictionary<string, string> GetI18NDataMapping()
        {
            return InternationalDataTools.LanguageMapping;
        }
    }
}
